package chis.fx.stage;

import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;







import chis.fx.handlers.MyHandler;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class Copy_2_of_BorderPaneStage extends Stage {

	// Constant data members.
	private final String stageTitle = "BorderPane Stage";
	private final double SCENE_WIDTH = 800;
	private final double SCENE_HEIGHT = 600;
	private final double SCENE_INSET_TOP = 10;
	private final double SCENE_INSET_RIGHT = 10;
	private final double SCENE_INSET_BOTTOM = 10;
	private final double SCENE_INSET_LEFT = 10;
	private final double HUD_WIDTH_PERCENT = 1;
	private final double HUD_HEIGHT_PERCENT = .30;
	private final double GAMECANVAS_WIDTH_PERCENT = 1;
	private final double GAMECANVAS_HEIGHT_PERCENT = .70;

	// Variable data members.

	// Layout dimensions.
	private double adjustedSceneWidth;
	private double adjustedSceneHeight;
	private double HUDWidth;
	private double HUDHeight;
	private double gameCanvasWidth;
	private double gameCanvasHeight;

	// Circle values.
	private double circleWidth;
	private double circleRadius;	
	private int numOfCirclesAcross;
	private int numOfCirclesDown;
	private int totalNumOfCircles;

	// Collection of clicked circle coordinates.
	private Map<Integer,MyPoint> circleCoordinates;

	private BorderPane root;
	private Scene scene;
	private FlowPane HUDPane;
	private FlowPane gameCanvasPane;
	//private Group circleGroup;

	private ArrayList<EventHandler<MouseEvent>> clickHandlerList;

	public Copy_2_of_BorderPaneStage(int numberOfCirclesAcross) {
		numOfCirclesAcross = numberOfCirclesAcross;

		clickHandlerList = new ArrayList<EventHandler<MouseEvent>>();

		circleCoordinates = new TreeMap<Integer,MyPoint>();
		initialiseMyStage();
	}

	private void initialiseMyStage() {
		this.setResizable(false);
		this.setTitle(stageTitle);

		root = new BorderPane();
		Insets insets = new Insets(SCENE_INSET_TOP,SCENE_INSET_RIGHT,SCENE_INSET_BOTTOM,SCENE_INSET_LEFT);
		root.setPadding(insets);

		scene = new Scene(root, SCENE_WIDTH, SCENE_HEIGHT, Color.PINK);

		layoutStage();	

		this.setScene(scene);
	}

	private void layoutStage() {
		adjustSceneDimensions();
		calculateHUDDimensions();
		calculateGameCanvasDimensions();
		makeHUD();
		makeGameCanvas();
		//testing();

		//endGame();
	}

	private void adjustSceneDimensions() {
		adjustedSceneWidth = SCENE_WIDTH - (SCENE_INSET_LEFT + SCENE_INSET_RIGHT);
		adjustedSceneHeight = SCENE_HEIGHT - (SCENE_INSET_TOP + SCENE_INSET_BOTTOM);
	}

	private void calculateHUDDimensions() {
		HUDWidth = HUD_WIDTH_PERCENT * adjustedSceneWidth;
		HUDHeight = HUD_HEIGHT_PERCENT * adjustedSceneHeight;
	}

	private void calculateGameCanvasDimensions() {
		gameCanvasWidth = GAMECANVAS_WIDTH_PERCENT * adjustedSceneWidth;
		gameCanvasHeight = GAMECANVAS_HEIGHT_PERCENT * adjustedSceneHeight;
	}

	private void makeHUD() {
		HUDPane = new FlowPane();
		HUDPane.setPrefSize(HUDWidth, HUDHeight);
		root.setTop(HUDPane);
	}

	private void makeGameCanvas() {
		gameCanvasPane = new FlowPane();
		gameCanvasPane.setPrefSize(gameCanvasWidth, gameCanvasHeight);
		initialiseCircleCollectionDimensions();

		for (int x = 0; x < totalNumOfCircles; x ++) {
			Circle c = new Circle(circleRadius, Color.web("white", 1));
			//c.setOnMouseClicked(null);

			EventHandler<MouseEvent>mc = makeCircleClickHandler();
			c.addEventHandler(MouseEvent.MOUSE_CLICKED, mc);

			//			c.addEventHandler(MouseEvent.MOUSE_CLICKED, makeCircleClickHandler());
			c.addEventHandler(MouseEvent.MOUSE_MOVED, makeCircleMovedHandler());
			c.addEventHandler(MouseEvent.MOUSE_ENTERED, makeCircleEnteredHandler());
			c.addEventHandler(MouseEvent.MOUSE_EXITED, makeCircleExitHandler());

			//c.removeEventHandler(MouseEvent.MOUSE_CLICKED, makeCircleClickHandler());

			gameCanvasPane.getChildren().add(c);
		}

		root.setCenter(gameCanvasPane);

	}

	private EventHandler<MouseEvent> makeCircleClickHandler(){
		EventHandler<MouseEvent> clickHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				MyPoint p = new MyPoint(event.getSceneX(),event.getSceneY());
				addClickedCircle(p);
			}
		};
		return clickHandler;
	}

	private EventHandler<MouseEvent> makeCircleMovedHandler(){
		EventHandler<MouseEvent> movedHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				System.out.println(event.getSceneX());
				System.out.println(event.getSceneY());
			}
		};
		return movedHandler;
	}

	private EventHandler<MouseEvent> makeCircleEnteredHandler(){
		EventHandler<MouseEvent> enteredHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				System.out.println("Entered");
			}
		};
		return enteredHandler;
	}

	private EventHandler<MouseEvent> makeCircleExitHandler(){
		EventHandler<MouseEvent> exitHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				System.out.println("Exited");
			}
		};
		return exitHandler;
	}

	private void endGame() {
		print("HERE","HERE");
		ObservableList<Node> l = gameCanvasPane.getChildren();
		for (int x = 0; x < l.size(); x++){
			Circle c = (Circle) l.get(x);
			print("1 c.onMouseClickedProperty()", c.onMouseClickedProperty());
			c.setOnMouseClicked(null);
			//c.removeEventHandler(MouseEvent.MOUSE_CLICKED, eventHandler);
			print("2 c.onMouseClickedProperty()", c.onMouseClickedProperty());

		}
	}

	private MyPoint getTopLeftPointOfPane(Pane parent, Pane child) {
		// Find the top left corner coordinates of the 
		// child pane inside the parent.
		MyPoint p = new MyPoint();
		int childIndex = parent.getChildren().indexOf(child);
		double minX = root.getChildren().get(childIndex).getBoundsInParent().getMinX();
		double minY = root.getChildren().get(childIndex).getBoundsInParent().getMinY();
		p.setX(minX);
		p.setY(minY);
		return p;
	}

	private MyPoint getPointInsideOfPane(MyPoint clickedPointInPane, MyPoint topLeftPointOfPane) {
		// Adjust the clicked coordinate in the scene
		// to the actual coordinate in the game canvas.
		MyPoint p = new MyPoint();
		p.setX(clickedPointInPane.getX() - topLeftPointOfPane.getX());
		p.setY(clickedPointInPane.getY() - topLeftPointOfPane.getY());
		return p;
	}

//	private int getPositionOnAxisPPP(double clickedCoord) {
//		// Divide the clicked coordinate by the circle's width
//		// to find the position of the circle (horizontal or vertical).
//		// Note: Circle width is the same as equal height.
//		int pos = (int) (clickedCoord / circleWidth);
//		return pos;
//	}
//
//	private int getPositionInGridPPP(MyPoint clickedInScene){
//		// Get topleft coord of game canvas.
//		MyPoint gameCanvasTopLeftCoords = getTopLeftPointOfPane(root,gameCanvasPane);
//		// Convert the scene coordinate to a game canvas coordinate.
//		MyPoint gameCanvasClickedPoint = getPointInsideOfPane(clickedInScene,gameCanvasTopLeftCoords);
//		// Get the index position the shape occupies on screen.
//		// eg. 1 circle across, 2 circles down.
//		// Note: Positions begin at zero.
//		int xPos = getPositionOnAxisPPP(gameCanvasClickedPoint.getX());
//		int yPos = getPositionOnAxisPPP(gameCanvasClickedPoint.getY());
//		// Get the index position of the shape.
//		//int position = getPositionInGrid(xPos,yPos);
//		// xPos and yPos range begin from 0.
//		// Convert xPos and yPos to position numbers
//		// by adding 1.
//		int convertToPositionNumberX = xPos + 1;
//		int convertToPositionNumberY = yPos + 1;
//		int positionNumber;
//		int balanceOfRow = numOfCirclesAcross - convertToPositionNumberX;
//		print("Balance of row", balanceOfRow);
//		positionNumber = (numOfCirclesAcross * convertToPositionNumberY) - balanceOfRow;
//		// Convert the position back to a range beginning with 0
//		// to ensure it's correct position in collections.
//		int indexPosition = positionNumber - 1;
//		return indexPosition;
//	}
//
//	private void addCirclesPPP(){
//		// Put the position index and coordinates of the shape into the map.
//				MyPoint p = getCoordinates(xPos,yPos);
//				circleCoordinates.put(position, p);
//	}
//
//	private void getCoordinatesPPP(){
//
//	}

	private void addClickedCircle(MyPoint clickedInScene) {
		// Get topleft coord of game canvas.
		MyPoint gameCanvasTopLeftCoords = getTopLeftPointOfPane(root,gameCanvasPane);
		// Convert the scene coordinate to a game canvas coordinate.
		MyPoint gameCanvasClickedPoint = getPointInsideOfPane(clickedInScene,gameCanvasTopLeftCoords);
		// Get the index position the shape occupies on screen.
		// eg. 1 circle across, 2 circles down.
		// Note: Positions begin at zero.
		int xPos = getPositionOnAxis(gameCanvasClickedPoint.getX());
		int yPos = getPositionOnAxis(gameCanvasClickedPoint.getY());
		// Get the index position of the shape.
		int position = getPositionInGrid(xPos,yPos);
		// Put the position index and coordinates of the shape into the map.
		MyPoint p = getCoordinates(xPos,yPos);
		circleCoordinates.put(position, p);

		//this.clickHandlerList.get(position);

		print("Added Position:: ",position);
		print("Added MyPoint:: ",p.toString());
		print("circleCoordinates.size", circleCoordinates.size());
	}

	private MyPoint getCoordinates(int xAxisPosition, int yAxisPosition) {
		MyPoint p = new MyPoint();
		int igameCanvasPane = root.getChildren().indexOf(gameCanvasPane);
		double minX = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinX();
		double minY = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinY();
		p.setX(minX + (xAxisPosition * circleWidth));
		p.setY(minY + (yAxisPosition * circleWidth));
		return p;
	}
	
	private int findNodeIndex(MyPoint clickedInScene) {
		
		return 0;
	}

	private int getPositionOnAxis(double clickedCoord) {
		// Divide the clicked coordinate by the circle's width
		// to find the position of the circle (horizontal or vertical).
		// Note: Circle width is the same as equal height.
		int pos = (int) (clickedCoord / circleWidth);
		return pos;
	}

	public int getPositionInGrid(int xAxisPosition, int yAxisPosition) {
		// xPos and yPos range begin from 0.
		// Convert xPos and yPos to position numbers
		// by adding 1.
		int convertToPositionNumberX = xAxisPosition + 1;
		int convertToPositionNumberY = yAxisPosition + 1;
		int positionNumber;
		int balanceOfRow = numOfCirclesAcross - convertToPositionNumberX;
		print("Balance of row", balanceOfRow);
		positionNumber = (numOfCirclesAcross * convertToPositionNumberY) - balanceOfRow;
		// Convert the position back to a range beginning with 0
		// to ensure it's correct position in collections.
		int indexPosition = positionNumber - 1;
		return indexPosition;
	}

	private void initialiseCircleCollectionDimensions() {
		circleWidth = gameCanvasWidth / numOfCirclesAcross;
		circleRadius = circleWidth / 2;
		numOfCirclesDown = (int) (gameCanvasHeight / circleWidth);
		totalNumOfCircles = numOfCirclesAcross * numOfCirclesDown;
	}

	private void getLocationOfGameCanvasInParent() {
		int igameCanvasPane = root.getChildren().indexOf(gameCanvasPane);
		double minX = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinX();
		double minY = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMinY();
		double maxX = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMaxX();
		double maxY = root.getChildren().get(igameCanvasPane).getBoundsInParent().getMaxY();
	}

	private EventHandler<MouseEvent> makeBorderPaneMovedHandler(){
		EventHandler<MouseEvent> clickHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				System.out.println("BorderPane " + event.getSceneX());
				System.out.println("BorderPane " + event.getSceneY());
			}
		};
		return clickHandler;
	}

	private EventHandler<MouseEvent> makeFlowPaneMovedHandler(){
		EventHandler<MouseEvent> clickHandler = new EventHandler<MouseEvent>() {
			public void handle(MouseEvent event) {
				System.out.println("FlowPane " + event.getSceneX());
				System.out.println("FlowPane " + event.getSceneY());
				int iHUDPane = root.getChildren().indexOf(HUDPane);
				System.out.println("iHUDPane: " + iHUDPane);
				int igameCanvasPane = root.getChildren().indexOf(gameCanvasPane);
				System.out.println("igameCanvasPane: " + igameCanvasPane);
				System.out.println("BOUNDS: " + root.getChildren().get(igameCanvasPane).getBoundsInParent());
			}
		};
		return clickHandler;
	}

	private void print(String tag, Object value) {
		System.out.println(tag + " " + value);
	}

	private void testing() {
		print("SCENE_WIDTH",SCENE_WIDTH);
		print("SCENE_HEIGHT",SCENE_HEIGHT);
		print("SCENE_INSET_TOP",SCENE_INSET_TOP);
		print("SCENE_INSET_RIGHT",SCENE_INSET_RIGHT);
		print("SCENE_INSET_BOTTOM",SCENE_INSET_BOTTOM);
		print("SCENE_INSET_LEFT",SCENE_INSET_LEFT);
		print("HUD_WIDTH_PERCENT",HUD_WIDTH_PERCENT);
		print("HUD_HEIGHT_PERCENT",HUD_HEIGHT_PERCENT);
		print("GAMECANVAS_WIDTH_PERCENT",GAMECANVAS_WIDTH_PERCENT);
		print("GAMECANVAS_HEIGHT_PERCENT",GAMECANVAS_HEIGHT_PERCENT);
		print("adjustedSceneWidth",adjustedSceneWidth);
		print("adjustedSceneHeight",adjustedSceneHeight);
		print("HUDWidth",HUDWidth);
		print("HUDHeight",HUDHeight);
		print("gameCanvasWidth",gameCanvasWidth);
		print("gameCanvasHeight",gameCanvasHeight);
		print("circleWidth",circleWidth);
		print("circleRadius",circleRadius);
		print("numOfCirclesAcross",numOfCirclesAcross);
		print("numOfCirclesDown",numOfCirclesDown);
		print("totalNumOfCircles",totalNumOfCircles);

		root.addEventHandler(MouseEvent.MOUSE_MOVED, makeBorderPaneMovedHandler());

		gameCanvasPane.addEventHandler(MouseEvent.MOUSE_MOVED, makeFlowPaneMovedHandler());


	}


}
